package com.yycx.generator.controller;

import cn.hutool.json.JSONObject;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.ds.ItemDataSource;
import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
import com.baomidou.mybatisplus.generator.config.po.TableField;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;

import com.yycx.generator.core.GeneratorCode;
import com.yycx.generator.core.GenField;
import com.yycx.generator.core.GenerateConfig;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.ibatis.jdbc.SqlRunner;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zyf
 */
@Controller
@RequestMapping("/generate/")
public class GenerateController {

    @Value("${yycx.front.path}")
    private String path;

    @Value("${spring.application.project}")
    private String project;

    @Value("${yycxgenerator.database:master}")
    private String database;

    @Resource
    private GeneratorCode generatorCode;
    @Resource
    public DataSourceConfig dataSourceConfig;

    @Resource
    private DynamicDataSourceProvider dynamicDataSourceProvider;

    @Resource
    private DynamicDataSourceProperties dynamicDataSourceProperties;

    @Resource
    private DynamicRoutingDataSource dynamicRoutingDataSource;


    /**
     * table列表
     *
     * @return
     */
    @GetMapping("/index")
    public String table() {
        return "tables.html";
    }

    /**
     * 生成配置
     *
     * @return
     */
    @GetMapping("/edit")
    public String edit(String tableName, Model model) {
        String projectPath = System.getProperty("user.dir");
        projectPath = projectPath.replaceAll("\\\\", "\\\\\\\\");

        model.addAttribute("tableName", tableName);
        model.addAttribute("projectPath", projectPath);
        model.addAttribute("webPath", path);
        model.addAttribute("projectBase", project);
        return "edit";
    }

    /**
     * 获取所有表信息
     *
     * @return
     */
    @PostMapping("/tables")
    @ResponseBody
    public JSONObject data() {
        JSONObject result = new JSONObject();
        GlobalConfig gc = new GlobalConfig();
        StrategyConfig strategy = new StrategyConfig();
        TemplateConfig templateConfig = new TemplateConfig();
        SqlRunner sqlRunner = null;
        List<Map<String, Object>> maps = new ArrayList<>();
        try {
            ItemDataSource itemDataSource = (ItemDataSource) dynamicRoutingDataSource.getDataSource(database);
            DataSource dataSource = itemDataSource.getDataSource();
            sqlRunner = new SqlRunner(dataSource.getConnection());
            maps = sqlRunner.selectAll("SHOW TABLE STATUS");
            sqlRunner.closeConnection();
        } catch (Exception e) {
            e.printStackTrace();
        }
        result.putOnce("data", maps);
        return result;
    }

    /**
     * 获取表信息
     *
     * @return
     */
    @PostMapping("/table")
    @ResponseBody
    public JSONObject table(String tableName) {
        JSONObject result = new JSONObject();
        GlobalConfig gc = new GlobalConfig();
        StrategyConfig strategy = new StrategyConfig();
        strategy.setInclude(tableName);
        TemplateConfig templateConfig = new TemplateConfig();
        Map<String, DataSourceProperty> dataSourceMap = dynamicDataSourceProperties.getDatasource();
        DataSourceProperty dataSourceProperty = (DataSourceProperty) dataSourceMap.get(database);
        dataSourceConfig.setDriverName(dataSourceProperty.getDriverClassName());
        dataSourceConfig.setPassword(dataSourceProperty.getPassword());
        dataSourceConfig.setUsername(dataSourceProperty.getUsername());
        dataSourceConfig.setSchemaName(dataSourceProperty.getSchema());
        dataSourceConfig.setUrl(dataSourceProperty.getUrl());
        ConfigBuilder config = new ConfigBuilder(new PackageConfig(), dataSourceConfig, strategy, templateConfig, gc);
        List<TableInfo> list = config.getTableInfoList();
        TableInfo tableInfo = list.get(0);
        Map<String, Object> map = new HashMap<>();
        List<TableField> fields = tableInfo.getFields();
        List<GenField> genFields = new ArrayList<>();
        for (TableField field : fields) {
            GenField genField = new GenField();
            BeanUtils.copyProperties(field, genField);
            String comment = genField.getComment();
            if (comment.indexOf("(") > -1) {
                genField.setComment(comment.substring(0, comment.indexOf("(")));
            }
            genField.setIsAdd(true);
            genField.setIsEdit(true);
            genField.setShowType("input");
            genField.setIsList(true);
            genField.setListSlot("text");
            genField.setIsSearch(false);
            genField.setSearchType("eq");
            genField.setIsRequired(false);
            if (!genField.getKeyFlag()) {
                genFields.add(genField);
            } else {
                map.put("rowKey", genField.getPropertyName());
            }
        }
        map.put("fields", genFields);
        map.put("menuName", tableInfo.getComment());
        result.putOnce("data", map);
        return result;
    }

    /**
     * 获取表信息
     *
     * @return
     */
    @PostMapping("/menus")
    @ResponseBody
    public JSONObject selectMenus() {
        JSONObject result = new JSONObject();
        List<Map<String, Object>> menus = new ArrayList<>();
        try {
            ItemDataSource itemDataSource = (ItemDataSource) dynamicRoutingDataSource.getDataSource(database);
            DataSource dataSource = itemDataSource.getDataSource();
            SqlRunner sqlRunner = new SqlRunner(dataSource.getConnection());
            String sql = "select menuId,menuName from base_menu where parentId=?";
            menus = sqlRunner.selectAll(sql, 0);
            sqlRunner.closeConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        result.putOnce("data", menus);
        return result;
    }

    /**
     * 生成代码
     *
     * @return
     */
    @PostMapping("/build")
    @ResponseBody
    public JSONObject build(GenerateConfig config) {
        JSONObject result = new JSONObject();
        String projectPath = config.getProjectPath();
        if (ObjectUtils.isEmpty(projectPath)) {
            String path = System.getProperty("user.dir");
            config.setProjectPath(path);
        }
        //是否覆盖生成文件
        config.setOverride(true);
        config.setBaseProject(false);
        //表名称
        config.setTableName(config.getTableName());
        generatorCode.init(config);
        result.putOnce("data", config);
        return result;
    }
}
